home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / file-tra / fsp-2.7 / fsp-2 / fsp / bsd_src / ls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-24  |  11.2 KB  |  444 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Michael Fischbein.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that: (1) source distributions retain this entire copyright
  10.  * notice and comment, and (2) distributions including binaries display
  11.  * the following acknowledgement:  ``This product includes software
  12.  * developed by the University of California, Berkeley and its contributors''
  13.  * in the documentation or other materials provided with the distribution
  14.  * and in all advertising materials mentioning features or use of this
  15.  * software. Neither the name of the University nor the names of its
  16.  * contributors may be used to endorse or promote products derived
  17.  * from this software without specific prior written permission.
  18.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  20.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  21.  */
  22.  
  23. #ifndef lint
  24. char copyright[] =
  25. "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
  26.  All rights reserved.\n";
  27. #endif /* not lint */
  28.  
  29. #ifndef lint
  30. static char sccsid[] = "@(#)ls.c    5.42 (Berkeley) 5/17/90";
  31. #endif /* not lint */
  32.  
  33. #include "tweak.h"
  34. #include "bsd_extern.h"
  35. #include "client_def.h"
  36. #include "c_extern.h"
  37. #ifndef VMS
  38. #include <sys/ioctl.h>
  39. #endif
  40. #include "my-string.h"
  41. #include "ls.h"
  42.  
  43. static char path[2*1024 + 1];
  44. static char *endofpath = path;
  45.  
  46. int (*sortfcn)PROTO0((LS *, LS*));
  47. void (*printfcn)PROTO0((LS *, int));
  48.  
  49. int termwidth = 80;        /* default terminal width */
  50.  
  51. /* flags */
  52. int f_accesstime;        /* use time of last access */
  53. int f_column;            /* columnated format */
  54. int f_group;            /* show group ownership of a file */
  55. int f_ignorelink;        /* indirect through symbolic link operands */
  56. int f_inode;            /* print inode */
  57. int f_kblocks;            /* print size in kilobytes */
  58. int f_listalldot;        /* list . and .. as well */
  59. int f_listdir;            /* list actual directory, not contents */
  60. int f_listdot;            /* list files beginning with . */
  61. int f_longform;            /* long listing format */
  62. int f_needstat;            /* if need to stat files */
  63. int f_newline;            /* if precede with newline */
  64. int f_nonprint;            /* show unprintables as ? */
  65. int f_nosort;            /* don't sort output */
  66. int f_recursive;        /* ls subdirectories also */
  67. int f_reversesort;        /* reverse whatever sort is used */
  68. int f_singlecol;        /* use single column output */
  69. int f_size;            /* list size in short listing */
  70. int f_statustime;        /* use time of last mode change */
  71. int f_dirname;            /* if precede with directory name */
  72. int f_timesort;            /* sort by time vice name */
  73. int f_total;            /* if precede with "total" line */
  74. int f_type;            /* add type character for non-regular files */
  75.  
  76. int tabdir PROTO2(LS *, lp, LS **, s_stats)
  77. {
  78.   register RDIR *dirp;
  79.   register int cnt, maxentry, maxlen;
  80.   register char *p;
  81.   struct rdirent *dp;
  82.   unsigned long blocks;
  83.   LS *stats;
  84.   
  85.   if (!(dirp = util_opendir("."))) {
  86.     perror(lp->name);
  87.     return(0);
  88.   }
  89.   blocks = maxentry = maxlen = 0;
  90.   stats = NULL;
  91.   for (cnt = 0; dp = util_readdir(dirp);) {
  92.     /* this does -A and -a */
  93.     p = dp->d_name;
  94.     if (p[0] == '.') {
  95.       if (!f_listdot) continue;
  96.       if (!f_listalldot && (!p[1] || p[1] == '.' && !p[2])) continue;
  97.     }
  98.     if (cnt == maxentry) {
  99. #define    DEFNUM    256
  100.       maxentry += DEFNUM;
  101.       if(stats) {
  102.     *s_stats = stats = (LS *)realloc((char *)stats,
  103.                      (unsigned int)maxentry * sizeof(LS));
  104.     if (!*s_stats) nomem();
  105.       } else {
  106.     *s_stats = stats = (LS *)malloc((unsigned int)maxentry * sizeof(LS));
  107.     if (!*s_stats) nomem();
  108.       }
  109.     }
  110.     if (f_needstat && util_stat(dp->d_name, &stats[cnt].lstat)) {
  111.       /*
  112.        * don't exit -- this could be an NFS mount that has
  113.        * gone away.  Flush stdout so the messages line up.
  114.        */
  115.       (void)fflush(stdout);
  116.       perror(dp->d_name);
  117.       continue;
  118.     }
  119.     stats[cnt].name = dp->d_name;
  120.     
  121.     /*
  122.      * get the inode from the directory, so the -f flag
  123.      * works right.
  124.      */
  125. #ifndef VMS
  126.     stats[cnt].lstat.st_ino = dp->d_fileno;
  127. #endif
  128.     
  129.     /* save name length for -C format */
  130.     stats[cnt].len = dp->d_namlen;
  131.     
  132.     /* calculate number of blocks if -l/-s formats */
  133.     if (f_longform || f_size) blocks += (stats[cnt].lstat.st_size+1023)/1024;
  134.     
  135.     /* save max length if -C format */
  136.     if (f_column && maxlen < (int)dp->d_namlen) maxlen = dp->d_namlen;
  137.     ++cnt;
  138.   }
  139.   (void)util_closedir(dirp);
  140.   
  141.   if (cnt) {
  142.     stats[0].lstat.st_btotal = blocks;
  143.     stats[0].lstat.st_maxlen = maxlen;
  144.   } else if (stats) {
  145.     (void)free((char *)stats);
  146.   }
  147.   return(cnt);
  148. }
  149.  
  150. static int displaydir PROTO0((LS *, register int));
  151.  
  152. static int subdir PROTO1(LS *, lp)
  153. {
  154.   LS *stats;
  155.   int num;
  156.  
  157.   if (f_newline) (void)putchar('\n');
  158.   if (f_dirname) (void)printf("%s:\n", path);
  159.  
  160.   if (util_cd2(lp->name)) {
  161.     perror(lp->name);
  162.     return;
  163.   }
  164.   if (num = tabdir(lp, &stats)) {
  165.     displaydir(stats, num);
  166.     (void)free((char *)stats);
  167.   }
  168.   if (util_cd2("..")) {
  169.     perror("..");
  170.     ls_bad(1);
  171.   }
  172. }
  173.  
  174. static int displaydir PROTO2(LS *, stats, register int, num)
  175. {
  176.   register char *p, *savedpath;
  177.   LS *lp;
  178.  
  179.   if (num > 1 && !f_nosort) {
  180.     unsigned long save1, save2;
  181.  
  182.     save1 = stats[0].lstat.st_btotal;
  183.     save2 = stats[0].lstat.st_maxlen;
  184.     qsort((char *)stats, num, sizeof(LS), sortfcn);
  185.     stats[0].lstat.st_btotal = save1;
  186.     stats[0].lstat.st_maxlen = save2;
  187.   }
  188.  
  189.   printfcn(stats, num);
  190.  
  191.   if (f_recursive) {
  192.     savedpath = endofpath;
  193.     for (lp = stats; num--; ++lp) {
  194.       if (!(S_ISDIR(lp->lstat.st_mode))) continue;
  195.       p = lp->name;
  196.       if (p[0] == '.' && (!p[1] || p[1] == '.' && !p[2])) continue;
  197.       if (endofpath != path && endofpath[-1] != '/') *endofpath++ = '/';
  198.       for (; *endofpath = *p++; ++endofpath);
  199.       f_newline = f_dirname = f_total = 1;
  200.       subdir(lp);
  201.       *(endofpath = savedpath) = '\0';
  202.     }
  203.   }
  204. }
  205.  
  206. static int doargs PROTO2(int, argc, char **, argv)
  207. {
  208.   register LS *dstatp, *rstatp;
  209.   register int cnt, dircnt, dirmax, maxlen, regcnt, regmax;
  210.   LS *dstats, *rstats;
  211.   struct stat sb;
  212.   char top[2*1024 + 1], **av, *av2[2];
  213.   unsigned long blocks;
  214.  
  215.   /*
  216.    * walk through the operands, building separate arrays of LS
  217.    * structures for directory and non-directory files.
  218.    */
  219.   dstats = rstats = NULL;
  220.   dirmax = regmax = 0;
  221.  
  222.   for (dircnt = regcnt = 0; *argv; ++argv)  {
  223.     if(!(av = glob(*argv))) {
  224.       av = av2;
  225.       av2[0] = *argv;
  226.       av2[1] = 0;
  227.     }
  228.     
  229.     for( ; *av; av++) {
  230.       if (util_stat(*av, &sb)) {
  231.     perror(*av);
  232.     if (errno == ENOENT) continue;
  233.     ls_bad(1);
  234.       }
  235.       if ((S_ISDIR(sb.st_mode)) && !f_listdir) {
  236.     if(dirmax == dircnt) {
  237.           dirmax += 10;
  238.           if (!dstats) {
  239.         dstatp = dstats = (LS *)emalloc(dirmax * (sizeof(LS)));
  240.           } else {
  241.         dstats = (LS *)realloc(dstats, dirmax * (sizeof(LS)));
  242.         dstatp = dstats + dircnt;
  243.           }
  244.     }
  245.     dstatp->name = *av;
  246.     dstatp->lstat = sb;
  247.     ++dstatp;
  248.     ++dircnt;
  249.       } else {
  250.     if(regmax == regcnt) {
  251.           regmax += 10;
  252.       if (!rstats) {
  253.         blocks = 0;
  254.         maxlen = -1;
  255.         rstatp = rstats = (LS *)emalloc(regmax * (sizeof(LS)));
  256.       } else {
  257.         rstats = (LS *)realloc(rstats, regmax * (sizeof(LS)));
  258.         rstatp = rstats + regcnt;
  259.       }
  260.     }
  261.     rstatp->name = *av;
  262.     rstatp->lstat = sb;
  263.  
  264.     /* save name length for -C format */
  265.     rstatp->len = strlen(*av);
  266.  
  267.     if (f_nonprint) prcopy(*av, *av, rstatp->len);
  268.  
  269.     /* calculate number of blocks if -l/-s formats */
  270.     if (f_longform || f_size) blocks += (sb.st_size + 1023)/1024;
  271.  
  272.     /* save max length if -C format */
  273.     if (f_column && maxlen < rstatp->len) maxlen = rstatp->len;
  274.     
  275.     ++rstatp;
  276.     ++regcnt;
  277.       }
  278.     }
  279.   }
  280.   /* display regular files */
  281.   if (regcnt) {
  282.     rstats[0].lstat.st_btotal = blocks;
  283.     rstats[0].lstat.st_maxlen = maxlen;
  284.     displaydir(rstats, regcnt);
  285.     f_newline = f_dirname = 1;
  286.   }
  287.   /* display directories */
  288.   if (dircnt) {
  289.     register char *p;
  290.  
  291.     f_total = 1;
  292.     if (dircnt > 1) {
  293.       (void)util_getwd(top);
  294.       qsort((char *)dstats, dircnt, sizeof(LS), sortfcn);
  295.       f_dirname = 1;
  296.     }
  297.     for (cnt = 0; cnt < dircnt; ++dstats) {
  298.       for (endofpath = path, p = dstats->name;
  299.        *endofpath = *p++; ++endofpath);
  300.       subdir(dstats);
  301.       f_newline = 1;
  302.       if (++cnt < dircnt && util_cd2(top)) {
  303.     perror(top);
  304.     ls_bad(1);
  305.       }
  306.     }
  307.   }
  308. }
  309.  
  310. void fls_main PROTO2(int, argc, char **, argv)
  311. {
  312.   extern int optind;
  313.   int ch;
  314.   char *p;
  315.  
  316.   /* terminal defaults to -Cq, non-terminal defaults to -1 */
  317.   if (isatty(1)) {
  318.     f_nonprint = 1;
  319.     termwidth  = 80;
  320. #ifdef TIOCGWINSZ
  321.     {
  322.       struct winsize win;
  323.       if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
  324.         if (p = (char *)getenv("COLUMNS")) termwidth = atoi(p);
  325.       } else termwidth = win.ws_col;
  326.     }
  327. #endif
  328.     f_column = 1;
  329.   } else f_singlecol = 1;
  330.  
  331.   /* root is -A automatically */
  332.   if (!getuid()) f_listdot = 1;
  333.  
  334.   while ((ch = getopt(argc, argv, "1ACFLRacdfgiklqrstu")) != EOF) {
  335.     switch (ch) {
  336.       /*
  337.        * -1, -C and -l all override each other
  338.        * so shell aliasing works right
  339.        */
  340.       case '1':
  341.         f_singlecol = 1;
  342.         f_column = f_longform = 0;
  343.         break;
  344.       case 'C':
  345.         f_column = 1;
  346.         f_longform = f_singlecol = 0;
  347.         break;
  348.       case 'l':
  349.         f_longform = 1;
  350.         f_column = f_singlecol = 0;
  351.         break;
  352.         /* -c and -u override each other */
  353.       case 'c':
  354.         f_statustime = 1;
  355.         f_accesstime = 0;
  356.         break;
  357.       case 'u':
  358.         f_accesstime = 1;
  359.         f_statustime = 0;
  360.         break;
  361.       case 'F':
  362.         f_type = 1;
  363.         break;
  364.       case 'L':
  365.         f_ignorelink = 1;
  366.         break;
  367.       case 'R':
  368.         f_recursive = 1;
  369.         break;
  370.       case 'a':
  371.         f_listalldot = 1;
  372.         /* FALLTHROUGH */
  373.       case 'A':
  374.         f_listdot = 1;
  375.         break;
  376.       case 'd':
  377.         f_listdir = 1;
  378.         break;
  379.       case 'f':
  380.         f_nosort = 1;
  381.         break;
  382.       case 'g':
  383.         f_group = 1;
  384.         break;
  385.       case 'i':
  386.         f_inode = 1;
  387.         break;
  388.       case 'k':
  389.         f_kblocks = 1;
  390.         break;
  391.       case 'q':
  392.         f_nonprint = 1;
  393.         break;
  394.       case 'r':
  395.         f_reversesort = 1;
  396.         break;
  397.       case 's':
  398.         f_size = 1;
  399.         break;
  400.       case 't':
  401.         f_timesort = 1;
  402.         break;
  403.       case '?':
  404.       default:
  405.         usage();
  406.     }
  407.   }
  408.   argc -= optind;
  409.   argv += optind;
  410.  
  411.   /* -d turns off -R */
  412.   if (f_listdir)
  413.     f_recursive = 0;
  414.  
  415.   /* if need to stat files */
  416.   f_needstat = f_longform || f_recursive || f_timesort || f_size || f_type;
  417.  
  418.   /* select a sort function */
  419.   if (f_reversesort) {
  420.     if (!f_timesort) sortfcn = revnamecmp;
  421.     else if (f_accesstime) sortfcn = revacccmp;
  422.     else if (f_statustime) sortfcn = revstatcmp;
  423.     else sortfcn = revmodcmp; /* use modification time */ 
  424.   } else {
  425.     if (!f_timesort) sortfcn = namecmp;
  426.     else if (f_accesstime) sortfcn = acccmp;
  427.     else if (f_statustime) sortfcn = statcmp;
  428.     else sortfcn = modcmp; /* use modification time */
  429.   }
  430.  
  431.   /* select a print function */
  432.   if (f_singlecol) printfcn = printscol;
  433.   else if (f_longform) printfcn = printlong;
  434.   else printfcn = printcol;
  435.  
  436.   if (!argc) {
  437.     argc = 1;
  438.     argv[0] = ".";
  439.     argv[1] = NULL;
  440.   }
  441.   doargs(argc, argv);
  442. }
  443.  
  444.